"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
// TypeScript 基础类型
// Boolean 类型
var isDone = false;
// Number类型
var count = 10;
// String
var nameS = "Semliker";
// Array 类型
var list = [1, 2, 3];
var list1 = [1, 2, 3];
// Enum 类型
// 数字枚举
var Direction;
(function (Direction) {
    Direction[Direction["NORTH"] = 1] = "NORTH";
    Direction[Direction["SOUTH"] = 2] = "SOUTH";
    Direction[Direction["EAST"] = 3] = "EAST";
    Direction[Direction["WEST"] = 4] = "WEST";
})(Direction || (Direction = {}));
var dir = Direction.NORTH;
// 字符串枚举
var DirectionS;
(function (DirectionS) {
    DirectionS["NORTH"] = "NORTH";
    DirectionS["SOUTH"] = "SOUTH";
    DirectionS["EAST"] = "EAST";
    DirectionS["WEST"] = "WEST";
})(DirectionS || (DirectionS = {}));
// 异构枚举
// 异构枚举的成员值是数字和字符串的混合：
var Enum3;
(function (Enum3) {
    Enum3[Enum3["A"] = 0] = "A";
    Enum3[Enum3["B"] = 1] = "B";
    Enum3["C"] = "C";
    Enum3["D"] = "D";
    Enum3[Enum3["E"] = 8] = "E";
    Enum3[Enum3["F"] = 9] = "F";
})(Enum3 || (Enum3 = {}));
// Any 类型
// Unknown 类型
// unknown 类型只能被赋值给 any 类型和 unknown 类型本身。直观地说，这是有道理的：只有能够保存任意类型值的容器才能保存 unknown 类型的值。毕竟我们不知道变量 value 中存储了什么类型的值。
// 元组 Tuple 类型
// 数组一般由同种类型的值组成，但有时我们需要在单个变量中存储不同类型的值，这时候我们就可以使用元组。
var tupleType;
tupleType = ["Semlinker", true]; //类型和数量都要对应
// 使用元组时，必须提供每个属性的值
// Void 类型
function warnUser() {
    console.log("This is my warning message");
}
// Null 和 Undefined 类型
// 默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number 类型的变量。然而，如果你指定了--strictNullChecks 标记，null 和 undefined 只能赋值给 void 和它们各自的类型。
// Never 类型
// never 类型表示的是那些永不存在的值的类型。 例如，never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
function infiniteLoop() {
    while (true) { }
}
function controlFlowAnalysisWithNever(foo) {
    if (typeof foo === "string") {
        // 这里 foo 被收窄为 string 类型
    }
    else if (typeof foo === "number") {
        // 这里 foo 被收窄为 number 类型
    }
    else {
        // foo 在这里是 never
        // 如果走到了这里会编译错误
        var check = foo;
    }
}
// 使用 never 避免出现新增了联合类型没有对应的实现，目的就是写出类型绝对安全的代码。
// TypeScript 断言
// “尖括号” 语法
var someValue = "this is a string";
var strLength = someValue.length;
// as 语法
var str1Length = someValue.length;
function printEmployeeInformation(emp) {
    console.log("Name: " + emp.name);
    if ("privileges" in emp) {
        console.log("Privileges: " + emp.privileges);
    }
    if ("startDate" in emp) {
        console.log("Start Date: " + emp.startDate);
    }
}
// typeof关键字
// typeof 类型保护只支持两种形式：typeof v === "typename" 和 typeof v !== typename，"typename" 必须是 "number"， "string"， "boolean" 或 "symbol"
function padLeft(value, padding) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error("Expected string or number, got '" + padding + "'.");
}
var SpaceRepeatingPadder = /** @class */ (function () {
    function SpaceRepeatingPadder(numSpaces) {
        this.numSpaces = numSpaces;
    }
    SpaceRepeatingPadder.prototype.getPaddingString = function () {
        return Array(this.numSpaces + 1).join(" ");
    };
    return SpaceRepeatingPadder;
}());
var StringPadder = /** @class */ (function () {
    function StringPadder(value) {
        this.value = value;
    }
    StringPadder.prototype.getPaddingString = function () {
        return this.value;
    };
    return StringPadder;
}());
var padder = new SpaceRepeatingPadder(6);
if (padder instanceof SpaceRepeatingPadder) {
    // padder的类型收窄为 'SpaceRepeatingPadder'
}
// 自定义类型保护的类型谓词
function isNumber(x) {
    return typeof x === "number";
}
function isString(x) {
    return typeof x === "string";
}
// 联合类型和类型别名
// 联合类型通常与 null 或 undefined 一起使用：
var sayHello = function (name) {
    /* ... */
};
// 可辨识联合
// 它包含 3 个要点：可辨识、联合类型和类型守卫。
var CarTransmission;
(function (CarTransmission) {
    CarTransmission[CarTransmission["Automatic"] = 200] = "Automatic";
    CarTransmission[CarTransmission["Manual"] = 300] = "Manual";
})(CarTransmission || (CarTransmission = {}));
// 使用switch case做类型守卫从而确保安全的访问到内部的属性
var EVALUATION_FACTOR = Math.PI;
function evaluatePrice(vehicle) {
    switch (vehicle.vType) {
        case "car":
            return vehicle.transmission * EVALUATION_FACTOR;
        case "truck":
            return vehicle.capacity * EVALUATION_FACTOR;
        case "motorcycle":
            return vehicle.make * EVALUATION_FACTOR;
    }
}
var greet = function (message) {
    // ...
};
// 函数
// 箭头函数
//  参数类型和返回类型
function createUserId(name, id) {
    return name + id;
}
// 前面四个是重载的方法 下面这个只是调用
function add(a, b) {
    if (typeof a === "string" || typeof b === "string") {
        return a.toString() + b.toString();
    }
    return a + b;
}
// TypeScript 数组
// 数组解构
var x;
var y;
var z;
var five_array = [0, 1, 2, 3, 4];
x = five_array[0], y = five_array[1], z = five_array[2];
// 数组展开运算符
var two_array = [0, 1];
var five_array1 = two_array.concat([2, 3, 4]);
// 数组遍历
var colors = ["red", "green", "blue"];
for (var _i = 0, colors_1 = colors; _i < colors_1.length; _i++) {
    var i = colors_1[_i];
    console.log(i);
}
// TypeScript 对象
var person = {
    name1: "Semlinker",
    gender: "Male",
};
var name1 = person.name1, gender = person.gender;
// 对象展开运算符
var person2 = {
    name2: "Semlinker",
    gender: "Male",
    address: "Xiamen",
};
// 组装对象
var personWithAge = __assign({}, person, { age: 33 });
// 获取除了某些项外的其它项
var name2 = person2.name2, rest = __rest(person2, ["name2"]);
var Semlinker = {
    name: "Semlinker",
    age: 33,
};
// 只读属性
// ReadonlyArray<T> 类型，它与 Array<T> 只是把所有可变方法去掉 确保数组首次创建后不可再被更改
var a = [1, 2, 3, 4];
var ro = a;
// ro[0] = 12; // error!
// TypeScript 类
// 我们可以通过 Class 关键字来定义一个类：
// 静态属性和方法只能通过类调用 不能通过实例调用
var Greeter = /** @class */ (function () {
    // 构造函数 - 执行初始化操作
    function Greeter(message) {
        this.greeting = message;
    }
    // 静态方法
    Greeter.getClassName = function () {
        return "Class name is Greeter";
    };
    // 成员方法
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    // 静态属性
    Greeter.cname = "Greeter";
    return Greeter;
}());
var greeter = new Greeter("world");
// 访问器  
//   我们可以通过 getter 和 setter 方法来实现数据的封装和有效性校验，防止出现异常数据。
var passcode = "Hello TypeScript";
var Employee = /** @class */ (function () {
    function Employee() {
        this._fullName = '';
    }
    Object.defineProperty(Employee.prototype, "fullName", {
        get: function () {
            return this._fullName;
        },
        set: function (newName) {
            if (passcode && passcode == "Hello TypeScript") {
                this._fullName = newName;
            }
            else {
                console.log("Error: Unauthorized update of employee!");
            }
        },
        enumerable: true,
        configurable: true
    });
    return Employee;
}());
var employee = new Employee();
employee.fullName = "Semlinker";
if (employee.fullName) {
    console.log(employee.fullName);
}
// 类的继承
// 通过extends关键字实现继承
// ECMAScript 私有字段
// 私有字段以 # 字符开头，有时我们称之为私有名称
// 私有字段不能在包含的类之外访问，甚至不能被检测到。
// es6之后
var Person = /** @class */ (function () {
    function Person(name) {
        this.;
        name = name;
    }
    Person.prototype.greet = function () {
        console.log("Hello, my name is " + this., name);
    };
    return Person;
}());
!");\n        }\n    }\n// TypeScript \u6CDB\u578B\n    // \u6CDB\u578B\uFF08Generics\uFF09\u662F\u5141\u8BB8\u540C\u4E00\u4E2A\u51FD\u6570\u63A5\u53D7\u4E0D\u540C\u7C7B\u578B\u53C2\u6570\u7684\u4E00\u79CD\u6A21\u677F\u3002\u76F8\u6BD4\u4E8E\u4F7F\u7528 any \u7C7B\u578B\uFF0C\u4F7F\u7528\u6CDB\u578B\u6765\u521B\u5EFA\u53EF\u590D\u7528\u7684\u7EC4\u4EF6\u8981\u66F4\u597D\uFF0C\u56E0\u4E3A\u6CDB\u578B\u4F1A\u4FDD\u7559\u53C2\u6570\u7C7B\u578B\u3002\n    // \u6CDB\u578B\u63A5\u53E3\n    interface GenericIdentityFn<T> {\n        (arg: T): T;\n    }\n    // \u6CDB\u578B\u7C7B\n    class GenericNumber<T> {\n        zeroValue: T;\n        add: (x: T, y: T) => T;\n      }\n    let myGenericNumber = new GenericNumber<number>();\n    myGenericNumber.zeroValue = 0;\n    myGenericNumber.add = function (x, y) {\n        return x + y;\n    };\n// \u6CDB\u578B\u5DE5\u5177\u7C7B\u578B\n    //   typeof  \u64CD\u4F5C\u7B26\u53EF\u4EE5\u7528\u6765\u83B7\u53D6\u4E00\u4E2A\u53D8\u91CF\u58F0\u660E\u6216\u5BF9\u8C61\u7684\u7C7B\u578B\u3002\n    //   keyof  \u64CD\u4F5C\u7B26\u53EF\u4EE5\u7528\u6765\u67E5\u627E\u4E00\u4E2A\u5BF9\u8C61\u4E2D\u7684\u6240\u6709 key \u503C\uFF1A\n    // in       \u7528\u6765\u904D\u5386\u679A\u4E3E\u7C7B\u578B\uFF1A\n        type Keys = \"a\" | \"b\" | \"c\"\n        type Obj =  {\n            [p in Keys]: any\n        } // -> { a: any, b: any, c: any }\n    // infer  \u5728\u6761\u4EF6\u7C7B\u578B\u8BED\u53E5\u4E2D\uFF0C\u53EF\u4EE5\u7528 infer \u58F0\u660E\u4E00\u4E2A\u7C7B\u578B\u53D8\u91CF\u5E76\u4E14\u5BF9\u5B83\u8FDB\u884C\u4F7F\u7528\u3002\n    type ReturnType<T> = T extends (\n        ...args: any[]\n    ) => infer R ? R : any;\n    // extends \u6709\u65F6\u5019\u6211\u4EEC\u5B9A\u4E49\u7684\u6CDB\u578B\u4E0D\u60F3\u8FC7\u4E8E\u7075\u6D3B\u6216\u8005\u8BF4\u60F3\u7EE7\u627F\u67D0\u4E9B\u7C7B\u7B49\uFF0C\u53EF\u4EE5\u901A\u8FC7 extends \u5173\u952E\u5B57\u6DFB\u52A0\u6CDB\u578B\u7EA6\u675F\u3002\n    interface ILengthwise {\n        length: number;\n      }\n    function loggingIdentity<T extends ILengthwise>(arg: T): T {\n        console.log(arg.length);\n        return arg;\n    }\n    // Partial Partial<T> \u7684\u4F5C\u7528\u5C31\u662F\u5C06\u67D0\u4E2A\u7C7B\u578B\u91CC\u7684\u5C5E\u6027\u5168\u90E8\u53D8\u4E3A\u53EF\u9009\u9879 ?\u3002\n    type Partial1<T> = {\n        [P in keyof T]?: T[P];\n    };\n    // \u5728\u4EE5\u4E0A\u4EE3\u7801\u4E2D\uFF0C\u9996\u5148\u901A\u8FC7 keyof T \u62FF\u5230 T \u7684\u6240\u6709\u5C5E\u6027\u540D\uFF0C\u7136\u540E\u4F7F\u7528 in \u8FDB\u884C\u904D\u5386\uFF0C\u5C06\u503C\u8D4B\u7ED9 P\uFF0C\u6700\u540E\u901A\u8FC7 T[P] \u53D6\u5F97\u76F8\u5E94\u7684\u5C5E\u6027\u503C\u3002\u4E2D\u95F4\u7684 ? \u53F7\uFF0C\u7528\u4E8E\u5C06\u6240\u6709\u5C5E\u6027\u53D8\u4E3A\u53EF\u9009\u3002\n      interface Todo {\n        title: string;\n        description: string;\n      }\n      function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {\n        return { ...todo, ...fieldsToUpdate };\n      }\n      \n      const todo1 = {\n        title: \"organize desk\",\n        description: \"clear clutter\",\n      };\n      \n      const todo2 = updateTodo(todo1, {\n        description: \"throw out trash\",\n      });\n    //   \u6211\u4EEC\u5229\u7528 Partial<T> \u5DE5\u5177\u7C7B\u578B\uFF0C\u5B9A\u4E49 fieldsToUpdate \u7684\u7C7B\u578B\u4E3A Partial<Todo>\n    // \u53D8\u6210\u4E86\n    // {\n    //     title?: string | undefined;\n    //     description?: string | undefined;\n    //  }\n\n// TypeScript \u88C5\u9970\u5668\n    //   \u7C7B\u88C5\u9970\u5668\n    // function Greeter1(greeting: string) {\n    //     return function (target: Function) {\n    //       target.prototype.greet = function (): void {\n    //         console.log(greeting);\n    //       };\n    //     };\n    //   }\n    //   @Greeter1(\"Hello TS!\")\n    //   class Greeting {\n    //     constructor() {\n    //       // \u5185\u90E8\u5B9E\u73B0\n    //     }\n    //   }\n    //   let myGreeting = new Greeting();\n    //   myGreeting.greet(); // console output: 'Hello TS!';\n      \n\n     \n\n      \n      \n      \n\n\n\n\n      \n\n\n      \n      ";
